package net.gdface.facelog;

import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeSet;
import java.util.Map.Entry;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.collect.Iterators;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

/**
 * 顶级组描述信息
 * @author guyadong
 *
 */
public class TopGroupInfo{
	/**
	 * 顶级组名,不可为空,字符串中的'/'会被替换成'_',空格会被清除
	 */
	private String name = "unknow_top_group";
	/**
	 * 创建设备组/人员组节点的描述<br>
	 * 配对创建(同名)人员组/设备组,并对配对授权,
	 * key为以'/'分隔符定义创建人员组/设备组叶子节点所属组的路径,为空则在顶级组名下创建
	 * value为','分隔的人员组/设备组叶子节点名称,字符串中的'/'会被替换成'_',空格会被清除
	 * <pre>
	 * 		'1幛/2单元' ---- '101,102,201,202'  # 创建在顶级组下级联创建名为'1幛','2单元'2个设备组+2个人员组,
	 *                                                         #并在'2单元'下创建名为'101,102,201,202'4个人员组+4个设备组,并对同名的设备组/人员名创建通行权限
	 * 		'1楼' ---- '8101房,8102房,8103房,8104房'
	 * 		'' --- '秋韵阁,春华阁'						# 在顶级组创建'秋韵阁,春华阁'3个人员组+3个设备组,并对同名的设备组/人员名创建通行权限
	 * </pre>
	 */
	private Map<String,String> nodes = Collections.emptyMap();
	/**
	 * 定义设备组授权<br>
	 * 健值对定义人员组授权设备通过权限<br>
	 * key为以'/'分隔的定义人员组的路径,为空则父节点为顶级组,如果路径节点不存在则创建
	 * value为','分隔的设备节点描述,至少包含两个','第一个元素为'/'分隔的定义设备组父节点的路径,为空则父节点为顶级组,
	 * 后续','的所有元素为该节点下的子节点名称(不递归),节点名中的'/'会被替换成'_',空格会被清除
	 * 如果只有两个元素,且第二个为通符符'*',则代表该父节点下的所有子节点(不递归)
	 * <pre>
	 * 		'1楼/保洁组' ---- '1楼,*'    # 授权'1楼/保洁组'在'1楼'设备组下所有节点的通行权限
	 * 		'1楼/保洁组' ---- '1楼'    # 授权'1楼/保洁组'在'1楼'设备组的通行权限(不包含子节点)
	 * 		'保安组' ---- ',东门,北门,停车场' # 授权'保安组'在顶级组下的'东门,北门,停车场'3个设备组的通行权限
	 * 		'' --- '停车场'      					# 授权顶级组下人员在顶级组下的'停车场'设备级的通行权限
	 * </pre>
	 */
	private Map<String,String> permits = Collections.emptyMap();
	/**
	 * 当存在同名的多个节点时是否清除多余的节点只保留1个
	 */
	private boolean clearMore = true;
	
	/**
	 * 当存在同名的顶级组时是否全部清除
	 */
	private boolean cleanExistingTop= true;

	/**
	 * 删除组时是否删除组下的元素(设备/人员)
	 */
	private boolean deleteElement = false;
	public TopGroupInfo() {
		super();
	}
	/**
	 * @return name
	 */
	public String getName() {
		return name;
	}
	/**
	 * @param name 要设置的 name
	 */
	public void setName(String name) {
		name = Strings.nullToEmpty(name).trim().replace('/', '_');
		if(!name.isEmpty()){
			this.name = name;
		}
	}
	/**
	 * @return nodes
	 */
	public Map<String, String> getNodes() {
		return nodes;
	}
	/**
	 * @param nodes 要设置的 nodes
	 */
	public void setNodes(Map<String, String> nodes) {
		if(nodes != null){
			this.nodes = nodes;
		}
	}
	/**
	 * @return permits
	 */
	public Map<String, String> getPermits() {
		return permits;
	}
	/**
	 * @param permits 要设置的 permits
	 */
	public void setPermits(Map<String, String> permits) {
		if(permits != null){
			this.permits = permits;
		}
	}
	/**
	 * @return clearMore
	 */
	public boolean isClearMore() {
		return clearMore;
	}
	/**
	 * @param clearMore 要设置的 clearMore
	 */
	public void setClearMore(boolean clearMore) {
		this.clearMore = clearMore;
	} 

	/**
	 * @return cleanExistingTop
	 */
	public boolean isCleanExistingTop() {
		return cleanExistingTop;
	}
	/**
	 * @param cleanExistingTop 要设置的 cleanExistingTop
	 */
	public void setCleanExistingTop(boolean cleanExistingTop) {
		this.cleanExistingTop = cleanExistingTop;
	}
	/**
	 * @return deleteElement
	 */
	public boolean isDeleteElement() {
		return deleteElement;
	}
	/**
	 * @param deleteElement 要设置的 deleteElement
	 */
	public void setDeleteElement(boolean deleteElement) {
		this.deleteElement = deleteElement;
	}
	public String fullPathOf(String input){
		if(input != null){
			if(input.startsWith(name) || input.startsWith("/" + name)){
				return input;
			}else if(input.isEmpty()){
				return name;
			}
			return name + "/" + input;
		}
		return input;
	}
	public static String normalizeNodePath(String path){
		return Strings.nullToEmpty(path)
				.replaceAll("\\s*", "")
				.replaceAll("//+", "/")
				.replaceAll("^/(.*)$", "$1")
				.replaceAll("(.*)/$", "$1");
	}
	public static String normalizeName(String name){
		return Strings.nullToEmpty(name)
				.replaceAll("\\s*", "")
				.replace('/', '_');
	}
	public static String normalizeElements(String names){
		names = normalizeName(names);
		String[] elements = names.split(",");
		if(elements.length > 1){
			Iterator<String> treeSet = sortAndClearDuplicated(Arrays.asList(elements).iterator());
			return Joiner.on(',').join(treeSet);
		}
		return elements[0];
	}
	/**
	 * 排序并去除重复
	 * @param itor
	 * @return
	 */
	public static Iterator<String> sortAndClearDuplicated(Iterator<String> itor){
		TreeSet<String> treeSet = Sets.newTreeSet();
		Iterators.addAll(treeSet, itor);
		return treeSet.iterator();
	}
	public static String[] parseNodes(String path){
		path = normalizeNodePath(path);
		if(path.isEmpty()){
			return new String[0];
		}
		return  path.split("/");
	}
	/**
	 * 路径及节点名称进行归一化处理<br>
	 * 清除所有字符串空格,叶子节点节点名称中的'/'替换为'_',并归一化路径名称,清除名字重复的叶子节点
	 */
	public void normalize(){
		name = normalizeName(name);
		if(!nodes.isEmpty()){
			Map<String, String> n = Maps.newHashMap();
			// 所有叶子节点节点名称中的'/'替换为'_'
			for(Entry<String, String> entry:nodes.entrySet()){
				n.put(normalizeNodePath(entry.getKey()), normalizeElements(entry.getValue()));
			}
			nodes = n;
		}
		if(!permits.isEmpty()){
			Map<String, String> p = Maps.newHashMap();
			for(Entry<String, String> entry:permits.entrySet()){
				String value = entry.getValue();
				int index = value.indexOf(',');
				if(index < 0){
					value = normalizeNodePath(value);
				}else{
					String path = normalizeNodePath(value.substring(0, index));
					String elements = normalizeElements(value.substring(index+1));
					if(elements.isEmpty()){
						value = path;
					}else{
						value = value + "," + elements;
					}				
				}
				p.put(normalizeNodePath(entry.getKey()), value);
			}
			permits = p;
		}
	}
}